package com.linkai.注解和反射.reflect;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * @Description: 动态的创建对象，通过反射
 * @Author: 林凯
 * @Date: 2021/10/21 19:11
 */
public class Test09 {
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
        // 获得 Class 对象
        Class<?> c1 = Class.forName("com.linkai.注解和反射.reflect.User");

        // 构造一个对象
        User user = (User)c1.newInstance();   // 本质上是调用了类的无参构造器
        System.out.println(user);

        // 通过构造器创建对象；想通过反射获取构造器，然后通过构造器的 newInstance() 方法
        Constructor<?> declaredConstructor = c1.getDeclaredConstructor(String.class, int.class, int.class);
        User user2 = (User) declaredConstructor.newInstance("jacklin", 1, 18);
        System.out.println(user2);

        // 通过反射调用方法：先通过反射获取方法，然后执行该方法的 invoke() 方法，同时将要执行该方法的对象以及方法的参数传入进去即可
        User user3 = (User)c1.newInstance();   // 本质上是调用了类的无参构造器
        // 通过反射获取一个方法
        Method setName = c1.getDeclaredMethod("setName", String.class);
        // invoke:激活的意思
        // （对象，“方法的值”）
        setName.invoke(user, "jacklin");
        System.out.println(user.getName());


        // 通过反射操作属性
        User user4 = (User)c1.newInstance();   // 本质上是调用了类的无参构造器
        Field name = c1.getDeclaredField("name");
        // name是私有属性不能直接访问，需要设置一下
        name.setAccessible(true);
        name.set(user4, "jacklin666");
        System.out.println(user4.getName());
    }
}
